/**
 * 
 */
package br.com.ac.fatureweb.view;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import javax.faces.event.ActionEvent;
import javax.faces.view.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;

import br.com.ac.fatureweb.integration.utilitary.NumberUtils;
import br.com.ac.fatureweb.integration.utilitary.NumberUtils.TypeDecimal;
import br.com.ac.fatureweb.jf.model.exporter.Ficha;
import br.com.ac.fatureweb.model.Carga;
import br.com.ac.fatureweb.model.billing.LogLeitura;
import br.com.ac.fatureweb.service.NgcExportacaoBean;
import br.com.ac.fatureweb.service.NgcRoteiroBean;
import br.com.ac.fatureweb.utilitary.FacesUtils;
import br.com.ac.fatureweb.utilitary.validator.OSValidator;

import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;

/**
 * @author aldivone
 *
 */
@Named
@ViewScoped
public class ExportacaoBean implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 944076850947534736L;

	@Inject
	private NgcRoteiroBean ngcRoteiroBean;

	@Inject
	private NgcExportacaoBean ngcExportacaoBean;

	private String url = "";

	private Carga carga;

	public void exportarSaae(ActionEvent event) {
		try {
			if (getCarga() == null || getCarga().getId() == null) {
				FacesUtils.addMessageError("Carga para retorno "
						+ "não foi selecionada!");
				return;
			}

			List<LogLeitura> resultList = ngcExportacaoBean
					.getLstLeituras(getCarga().getId());

			if (resultList != null && !resultList.isEmpty()) {

				List<Ficha> lstFicha = getLstDadosExportar(getCarga().getId(),
						resultList);

				final JsonArray array = new JsonArray();

				for (final Object ficha : lstFicha) {

					JsonElement fichaJson = new Gson().toJsonTree(ficha);

					array.add(fichaJson);
				}

				HttpURLConnection httpcon = enviarDados(array);

				StringBuffer respostaSaae = lerResposta(httpcon);

				// Marcar os log leitura como enviados.

				// Se todos os imóveis estiverem retornados não
				if (carga != null
						&& carga.getQtdImovel() != null
						&& carga.getQtdImovelRetornado() != null
						&& carga.getQtdImovel().equals(
								carga.getQtdImovelRetornado())) {
					atualizarRetornados(lstFicha, resultList);
					ngcRoteiroBean.marcarRoteiroSaae(getCarga().getId());
				} else {
					atualizarRetornados(lstFicha, resultList);
				}

				if (respostaSaae != null) {
					FacesUtils.addMessageInformation(respostaSaae.toString());
				} else {
					FacesUtils
							.addMessageInformation("Processamento efetuado com sucesso!");
				}

			} else {
				FacesUtils.addMessageInformation("Não existem leituras"
						+ " para retornar ao SAAE!");
			}
		} catch (IOException ex) {
			ex.printStackTrace();
			FacesUtils.addMessageError("Erro retornado da JF: "
					+ ex.getMessage());

		} catch (Exception ex) {
			ex.printStackTrace();
			FacesUtils.addMessageError("Erro no "
					+ "processamento da carga de retorno ao SAAE.");
		}
	}

	private void atualizarRetornados(List<Ficha> lstFicha,
			List<LogLeitura> resultList) {
		Integer qtdImovelRetornado = 0;

		qtdImovelRetornado = lstFicha.size();

		getCarga().setQtdImovelRetornado(qtdImovelRetornado);

		ngcRoteiroBean.atualizarCarga(getCarga());

		for (LogLeitura logLeitura : resultList) {
			ngcRoteiroBean.marcarLogLeituraEnviado(logLeitura.getSeq());
		}
	}

	public List<Ficha> getLstDadosExportar(Long id, List<LogLeitura> resultList) {

		List<Ficha> lstFichas = new ArrayList<Ficha>();

		if (resultList != null && !resultList.isEmpty()) {

			for (LogLeitura logLeitura : resultList) {

				Ficha ficha = new Ficha();

				ficha.setInscricao(logLeitura.getInscricao().toString());

				ficha.setMes(logLeitura.getMes().toString());

				ficha.setAno(logLeitura.getAno().toString());

				if (logLeitura.getLeitura() != null) {
					ficha.setLeitura(logLeitura.getLeitura().toString());
				} else {
					ficha.setLeitura("0");
				}

				DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy",
						new Locale("pt", "BR"));

				ficha.setDataLeitura(dateFormat.format(logLeitura
						.getDataLeitura()));

				dateFormat = new SimpleDateFormat("hh:mm", new Locale("pt",
						"BR"));

				ficha.setHoraLeitura(dateFormat.format(logLeitura
						.getDataLeitura()));

				if (logLeitura.getConsumo() != null) {
					ficha.setConsumo(logLeitura.getConsumo().toString());
				} else {
					ficha.setConsumo("0");
				}

				// codigo saae
				ficha.setCodLeiturista(ngcExportacaoBean
						.getCodLeituristaSaae(logLeitura.getIdLeiturista()));

				if (logLeitura.getCodOcorrencia1() != null) {
					ficha.setCodOcorrencia1(logLeitura.getCodOcorrencia1()
							.toString());
				} else {
					ficha.setCodOcorrencia1("0");
				}

				/*
				 * David solicitou em 27/05/2015: o "COD_OCORRENCIA2":"null"
				 * está retornando null poderia deixar ele fixo com 0
				 * "LATITUDE":"null" "LONGITUDE":"null" se forem "null" retornar
				 * ""
				 */
				ficha.setCodOcorrencia2("0");

				if (logLeitura.getValorAgua() != null) {
					ficha.setValorAgua(NumberUtils.truncateValue(
							logLeitura.getValorAgua(), TypeDecimal.TWO_DECIMAL));
				} else {
					ficha.setValorAgua(0D);
				}

				if (logLeitura.getValorEsgoto() != null) {
					ficha.setValorEsgoto(NumberUtils.truncateValue(
							logLeitura.getValorEsgoto(),
							TypeDecimal.TWO_DECIMAL));
				} else {
					ficha.setValorEsgoto(0D);
				}

				if (logLeitura.getValorServicos() != null) {
					ficha.setValorServicos(NumberUtils.truncateValue(
							logLeitura.getValorServicos(),
							TypeDecimal.TWO_DECIMAL));
				} else {
					ficha.setValorServicos(0D);
				}

				if (logLeitura.getValorTotal() != null) {
					ficha.setValorTotal(NumberUtils.truncateValue(
							logLeitura.getValorTotal(), TypeDecimal.TWO_DECIMAL));
				} else {
					ficha.setValorTotal(0D);
				}

				if (logLeitura.getLatitude() != null) {
					ficha.setLatitude(logLeitura.getLatitude().toString());
				} else {
					ficha.setLatitude("");
				}

				if (logLeitura.getLongitude() != null) {
					ficha.setLongitude(logLeitura.getLongitude().toString());
				} else {
					ficha.setLongitude("");
				}

				lstFichas.add(ficha);

			}
		}

		return lstFichas;
	}

	private HttpURLConnection enviarDados(final JsonArray array)
			throws IOException, MalformedURLException, ProtocolException,
			UnsupportedEncodingException {

		byte[] outputBytes = array.toString().getBytes("UTF-8");

		SimpleDateFormat simpleDateFormat = new SimpleDateFormat(
				"dd_MM_yyyy_hh_mm_ss");

		Date date = new Date();

		if (OSValidator.isWindows()) {
			byte[] bytes = gerarConteudoArquivoJson(array);

			FacesUtils.writeVfsFile("C:/ifature/arquivos/", "retorno_"
					+ simpleDateFormat.format(date) + ".json", bytes, false);
		} else {
			byte[] bytes = gerarConteudoArquivoJson(array);

			FacesUtils.writeVfsFile("/ifature/arquivos/", "retorno_"
					+ simpleDateFormat.format(date) + ".json", bytes, true);
		}

		FacesUtils.addMessageInformation("Arquivo para envio ao sai foi"
				+ " gerado com sucesso! \n Procurar o arquivo "
				+ "na pasta: C:/ifature/arquivos/");

		try {
			HttpURLConnection httpcon = (HttpURLConnection) ((new URL(url)
					.openConnection()));

			httpcon.setDoOutput(true);
			httpcon.setDoInput(true);
			httpcon.setRequestProperty("Content-Type", "application/json");
			httpcon.setRequestProperty("Accept", "application/json");
			httpcon.setRequestMethod("POST");
			httpcon.setReadTimeout(10000);
			httpcon.setConnectTimeout(15000);
			httpcon.connect();

			OutputStream os = httpcon.getOutputStream();

			os.write(outputBytes);

			os.flush();

			os.close();

			return httpcon;
		} catch (Exception ex) {
			ex.printStackTrace();
		}

		return null;
	}

	private byte[] gerarConteudoArquivoJson(final JsonArray array)
			throws UnsupportedEncodingException {
		StringBuilder contArquivo = new StringBuilder("{ \"ficha\":");
		contArquivo.append(array.toString());
		contArquivo.append("}");

		byte[] bytes = contArquivo.toString().getBytes("UTF-8");
		return bytes;
	}

	private StringBuffer lerResposta(HttpURLConnection httpcon)
			throws UnsupportedEncodingException, IOException {
		if (httpcon != null) {

			BufferedReader br = new BufferedReader(new InputStreamReader(
					httpcon.getInputStream(), "UTF-8"));

			StringBuffer dadosUrl = new StringBuffer();
			String dado = "";
			while (null != ((dado = br.readLine()))) {
				dadosUrl.append(dado);
			}
			br.close();
			return dadosUrl;
		}
		return null;
	}

	public List<Carga> getLstCarga() {
		return ngcRoteiroBean.getLstCargaRetorno();
	}

	/**
	 * @return the carga
	 */
	public Carga getCarga() {
		return carga;
	}

	/**
	 * @param carga
	 *            the carga to set
	 */
	public void setCarga(Carga carga) {
		this.carga = carga;
	}

	/**
	 * @return the url
	 */
	public String getUrl() {
		return url;
	}

	/**
	 * @param url
	 *            the url to set
	 */
	public void setUrl(String url) {
		this.url = url;
	}

}
